#include "raft_utils/Persistence.h"

#include <fstream>
#include <ios>

#include "raft_utils/Config.h"

raft::utils::Persistence::Persistence(const std::string &me)
    : raft_state_file_name_("raft_state_persist_" + me),
      snapshot_file_name_("snapshot_persist_" + me),
      raft_state_size_(0),
      log(bq::log::get_log_by_name(raft::utils::Config::getInstance()->get_log_name())) {
    log.verbose("Start: raft::utils::Persistence::Persister(const int me)");
    log.verbose("End: raft::utils::Persistence::Persister(const int me)");
}

bool raft::utils::Persistence::save(const std::string &raft_state, const std::string &snapshot) {
    log.verbose("Start: void raft::utils::Persistence::save(const std::string &raft_state, const std::string &snapshot)");
    std::lock_guard<std::mutex> lock(mutex_);

    // 保存raft状态
    std::ofstream raft_state_file(raft_state_file_name_, std::ios::out | std::ios::trunc);
    if (!raft_state_file.is_open()) {
        log.error("Failed to open raft state file for writing");
        return false;
    }
    raft_state_file << raft_state;
    raft_state_file.close();

    // 保存快照
    std::ofstream snapshot_file(snapshot_file_name_, std::ios::out | std::ios::trunc);
    if (!snapshot_file.is_open()) {
        log.error("Failed to open snapshot file for writing");
        return false;
    }
    snapshot_file << snapshot;
    snapshot_file.close();

    raft_state_size_ = static_cast<long long>(raft_state.size());
    log.verbose("End: void raft::utils::Persistence::save(const std::string &raft_state, const std::string &snapshot)");
    return true;
}

bool raft::utils::Persistence::save_raft_state(const std::string &data) {
    log.verbose("Start: bool raft::utils::Persistence::save_raft_state(const std::string &data)");

    std::lock_guard<std::mutex> lock(mutex_);

    std::ofstream raft_state_file(raft_state_file_name_, std::ios::out | std::ios::trunc);
    if (!raft_state_file.is_open()) {
        log.error("Failed to open raft state file for writing");
        return false;
    }
    raft_state_file << data;
    raft_state_file.close();

    raft_state_size_ = static_cast<long long>(data.size());

    log.verbose("End: bool raft::utils::Persistence::save_raft_state(const std::string &data)");
    return true;
}

std::string raft::utils::Persistence::read_raft_state() {
    log.verbose("Start: std::string raft::utils::Persistence::read_raft_state()");
    std::lock_guard<std::mutex> lock(mutex_);

    std::ifstream fs(raft_state_file_name_, std::ios_base::in | std::ios_base::binary);
    if (!fs.good()) {
        log.error("[func-raft::utils::Persistence::read_raft_state] Unable to open raft state file for reading.");
        return "";
    }
    std::string data((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>());
    fs.close();
    log.verbose("End: std::string raft::utils::Persistence::read_raft_state()");
    return data;
}

std::string raft::utils::Persistence::read_snapshot() {
    log.verbose("Start: std::string raft::utils::Persistence::read_snapshot()");
    std::lock_guard<std::mutex> lock(mutex_);
    std::ifstream fs(snapshot_file_name_, std::ios_base::in | std::ios_base::binary);
    if (!fs.good()) {
        log.error("[func-raft::utils::Persistence::read_snapshot] snapshot_file open error");
        return "";
    }
    std::string data((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>());
    fs.close();
    log.verbose("End: std::string raft::utils::Persistence::read_snapshot()");
    return data;
}

long long raft::utils::Persistence::get_raft_state_size() const {
    log.verbose("Start: long long raft::utils::Persistence::get_raft_state_size() const");
    log.verbose("End: long long raft::utils::Persistence::get_raft_state_size() const");
    return raft_state_size_;
}
